﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
using System.IO;
using System.Collections.ObjectModel;

namespace EzDesk.Generic
{
    public static class IEnumerableExt
    {
        public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> items)
        {
            var result = new ObservableCollection<T>();
            if(items ==null) return result;

            foreach (var item in items)
            {
                 result.Add(item);
            }
            return result;
        }

        public static ObservableCollection<T> AddRange<T>(this ObservableCollection<T> source,IEnumerable<T> items)
        {
            foreach (var item in items)
            {
                source.Add(item);
            }
            return source;
        }

        public static IEnumerable<T> Foreach<T>(this IEnumerable<T> items, Action<T> method)
        {
            foreach (var item in items)
                method(item);
            return items;
        }

        public static IEnumerable<T> Foreach<T>(this IEnumerable<T> items, Action<T, int> method)
        {
            int i = 0;
            foreach (var item in items)
            {
                method(item, i);
                i++;
            }
            return items;
        }

        public static IEnumerable<T1> Foreach<T1,T2>(this IEnumerable<T1> items, Action<T1,T2> method, T2 arg1)
        {
            foreach (var item in items)
                method(item, arg1);
            return items;
        }

        public static IEnumerable<TResult> Foreach<T, TResult>(this IEnumerable<T> items, Func<T, TResult> method)
        {
            List<TResult> results = new List<TResult>();
            foreach (var item in items)
                results.Add(method(item));
            return results;
        }

        public static IEnumerable<TResult> Foreach<T, TResult>(this IEnumerable<T> items, Func<T, int, TResult> method)
        {
            int i = 0;
            List<TResult> results = new List<TResult>();
            foreach (var item in items)
            {
                results.Add(method(item, i));
                i++;
            }
            return results;
        }

        public static string[] ToStringArrary<T>(this IEnumerable<T> items)
        {
            return items.Select(i => i.ToString()).ToArray();
        }
        public static string Join<T>(this IEnumerable<T> items, string split)
        {
            return string.Join(split, items.ToStringArrary<T>());
        }
        public static IEnumerable<string> ToStringArrary<T>(this IEnumerable<T> items, Func<T, string> fun)
        {
            return items.Select(i => fun(i));
        }
        public static string Join<T>(this IEnumerable<T> items, string split, Func<T, string> fun)
        {
            return string.Join(split, items.ToStringArrary<T>(fun).ToArray());
        }
    }

    public static class DictionaryExt
    {
        public static Dictionary<TKey, TValue> AddRange<TKey, TValue>(this Dictionary<TKey, TValue> source, Dictionary<TKey, TValue> values)
        {
            foreach (var item in values)
            {
                source[item.Key] = item.Value;
            }
            return source;
        }

        public static Dictionary<TKey, TValue> AddRange<TKey, TValue>(this Dictionary<TKey, TValue> source, IEnumerable<KeyValuePair<TKey, TValue>> values)
        {
            foreach (var item in values)
            {
                source[item.Key] = item.Value;
            }
            return source;
        }
    }



    public static class EnumExt
    {
        public static string GetEnumName(this Enum enumType)
        {
            return Enum.GetName(enumType.GetType(), enumType);
        }
        public static IList<string> GetAllEnums(this Enum enumType)
        {
            return Enum.GetNames(enumType.GetType()).ToList();
        }
    }


    public static class Extension
    {
        public static bool TrueDo(this bool source, Action method)
        {
            if (source) method();
            return source;
        }
        public static bool FalseDo(this bool source, Action method)
        {
            if (!source) method();
            return source;
        }
        public static bool TrueOrFalseDo_Action(this bool source, Action tureDoMethod, Action falseDoMethod)
        {
            if (source) tureDoMethod();
            else falseDoMethod();
            return source;
        }
        public static bool TrueOrFalseDo_Func(this bool source, Func<object> tureDoMethod, Func<object> falseDoMethod)
        {
            if (source) tureDoMethod();
            else falseDoMethod();
            return source;
        }
        public static void TrueDo(this bool source, object obj)
        {
        }
        public static void ExecuteMethod(this EventHandler source, object sender, EventArgs e)
        {
            EventHandler handler = source;
            if (handler != null)
            {
                handler(sender, e);
            }
        }
        public static void ExecuteMethod<T>(this EventHandler source, object sender, T e) where T : EventArgs
        {
            EventHandler handler = source;
            if (handler != null)
            {
                handler(sender, e);
            }
        }

        public static void ExecuteMethod<T>(this EventHandler<GenericEventArg<T>> source, object sender, T e)
        {
            EventHandler<GenericEventArg<T>> handler = source;
            if (handler != null)
            {
                handler(sender, new GenericEventArg<T>(e));
            }
        }

        public static bool Between(this int source, int min, int max)
        {
            if (source >= min && source <= max) return true;

            return false;
        }
        public static bool BetweenFrom(this int source, int from, int to)
        {
            return source.Between(from, to - 1);
        }
        public static bool BetweenTo(this int source, int from, int to)
        {
            return source.Between(from + 1, to);
        }


    }

    public static class XConvertExt
    {
        public static string ToXmlString(this object obj)
        {
            return obj.ToXmlString(false);
        }
        public static string ToXmlString(this object obj, bool omitXmlDeclaration)
        {
            XmlSerializer xmlS = new XmlSerializer(obj.GetType());
            StringBuilder xmlStr = new System.Text.StringBuilder();
            XmlWriterSettings setting = new XmlWriterSettings { OmitXmlDeclaration = omitXmlDeclaration };
            xmlS.Serialize(XmlWriter.Create(xmlStr, setting), obj);
            return xmlStr.ToString();
        }

        public static T GetFromXmlString<T>(this string xmlString)
        {
            XmlSerializer xmlS = new XmlSerializer(typeof(T));
            return (T)xmlS.Deserialize(XmlReader.Create((new StringReader(xmlString))));

        }


    }

    public static class ObservableCollectionExt
    {

        public static ObservableCollection<TItem> InsertOnTopWithRange<TItem>(this ObservableCollection<TItem> source, IEnumerable<TItem> items)
        {

            foreach (var item in items.Reverse())
            {
                source.Insert(0, item);
            }
            return source;
        }
    }


    public static class SortedListExt
    {
        public static List<TValue> Take<TKey, TValue>(this SortedList<TKey, TValue> source, int count, Func<TValue, bool> filter, bool Desc = false)
        {
            List<TValue> result = new List<TValue>();
            int limit = Math.Min(count, source.Count);
            int currentCount = 0;

            for (int seed = 0; seed < source.Count; seed++)
            {
                int index = Desc ? source.Count - seed - 1 : seed;
                TValue value = source.Values[index];
                if (filter(value))
                {
                    result.Add(value);
                    currentCount++;
                }

                if (currentCount == count) break;
            }

            return Desc ? result : result.Reverse<TValue>().ToList();
        }
    }
    public static class DateTimeExt
    {
        public static string ToFriendlyString(this DateTime source)
        {
            string date = source.ToFriendlyDateString();
            if (date == "今天")
                return string.Format("{0}", source.ToFriendlyTimeString());
            else
                return string.Format("{0} {1}", date, source.ToFriendlyTimeString());

        }
        public static string ToFriendlyDateString(this DateTime source)
        {
            int day = (DateTime.Now.Date - source.Date).Days;
            if (day == 0)
                return "今天";
            else if (day == 1)
                return "昨天";
            else if (day == 2)
                return "前天";
            else
                return DateTime.Now.Date.ToString("yy.MM.dd");
        }
        public static string ToFriendlyTimeString(this DateTime source)
        {
            DateTime current = DateTime.Now;
            if (current.Date == source.Date)
            {
                TimeSpan d = (current - source);
                if (d.Minutes == 0)
                {
                    return "刚到";
                }
                else if (d.Minutes < 60)
                {
                    return string.Format("{0}分钟前", d.Minutes);
                }
                else
                {
                    return string.Format("{0}小时前", d.Hours);
                }
            }
            else
                return source.ToString("hh:mm");
        }

    }

}
